package ru.averta.notes.service.security.token;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import ru.averta.notes.other.UtilsApi;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <code>TokenBasedAuthenticationFilter</code>
 *
 * Производит аудентификацию, создает и соханяет токен
 *
 * @author fedor.belov (fedor.belov@mail.ru)
 *         Date: 02.09.11 15:06
 */
public class TokenBasedAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    public TokenBasedAuthenticationFilter() {
        //Указываем в каком случае использовать фильтр
        setFilterProcessesUrl("/api/login");

        //Т.к. при любом результате login'а необходимо продолжить chain, приходится управлять ходом исполнения программы при помощи Exception'ов =(
        setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {

            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                throw new SuccessAuthException();
            }
        });

        setAuthenticationFailureHandler(new AuthenticationFailureHandler() {
            @Override
            public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                throw new FailureAuthException();
            }
        });
    }

    /**
     * Производит аудентификацию на освновании переданных данных - login, password
     * По результатам аудентификации вызываются соотв. хендлеры, которые генерируют Exception'ы
     * В случае успешного логина (SuccessAuthException) запрос помечается успешно прошедшим удентификацию
     *
     * В любом случае исполнение цепочки продолжается
     *
     * @param req
     * @param res
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        try {
            super.doFilter(req, res, chain);
        } catch (SuccessAuthException successAuth) {
            //Помечаем, что аудентификация прошла и продолжаем исполнение запроса
            UtilsApi.setSuccessfulAuth(req);
            chain.doFilter(req, res);
        } catch (FailureAuthException failAuth) {
            //Ничего не делаем... просто не помечаем запрос
            chain.doFilter(req, res);
        }

    }

    @Override
    protected String obtainPassword(HttpServletRequest request) {
//        return request.getHeader(SPRING_SECURITY_FORM_PASSWORD_KEY);
        //TODO
        return "test1";
    }

    @Override
    protected String obtainUsername(HttpServletRequest request) {
//        return request.getHeader(SPRING_SECURITY_FORM_USERNAME_KEY);
        return "test1@mail.ru";
    }

    public class SuccessAuthException extends RuntimeException {}
    public class FailureAuthException extends RuntimeException {}

}
